Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Blade ID Scan Millis Timeout #697

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

cshannon2
Copy link

This pull request adds a timeout to the BLADE_ID_SCAN_MILLIS option. Currently if BLADE_ID_SCAN_MILLIS is enabled it will constantly check for a blade configuration even when the lightsaber is not in use. A side effect of BLADE_ID_SCAN_MILLIS is a blinking light. The blinking light can be observed long after the lightsaber has been in use. The timeout allows the lightsaber to stop searching for a blade if it hasn't been turned on in a certain amount of time. The default time is 10 minutes. The value can be changed via a config file.

The logic:
If the blade is off and the blade has been off for longer than the timeout, then the proffie board can stop searching for a blade. BLADE_ID_SCAN_MILLIS can be resumed by turning the lightsaber on and off. Once the lightsaber is turned off the board will restart the countdown.

@profezzorn
Copy link
Owner

Interesting, but maybe we should just be using IDLE_OFF_TIME for this?

@cshannon2
Copy link
Author

cshannon2 commented Sep 29, 2024

Great Observation. I actually started this using IDLE_OFF_TIME. I was using the variable that IDLE_OFF_TIME creates which is called: last_on_time_.

The If statement logic looked like this:
if (IsOn() == false && (now - last_on_time_) < BLADE_ID_SCAN_TIMEOUT)

During testing I noticed that I was running into an issue with the BLADE_ID_SCAN_MILLIS unexpectedly restarting after a timeout had occurred. I found that it was because there is another function that modifies last_on_time_.

if (millis() - last_on_time_ > IDLE_OFF_TIME) { SaberBase::DoOff(OFF_IDLE, 0); last_on_time_ = millis(); }

The above code appeared to be resetting the timeout which resulted in restarting the BLADE_ID_SCAN_MILLIS without the lightsaber being powered on.

I wasn't sure why last_on_time_ was being reset in that function. If we can remove the last_on_time_ = millis(); from that function then I believe that I could change this to use the last_on_time_ variable.

I created BLADE_ID_SCAN_TIMEOUT instead of using IDLE_OFF_TIME to allow users to turn off the blinking light side effect without impacting other leds.

@NoSloppy
Copy link
Contributor

blinking light side effect

By this do you mean like a single "weak" LED such as on an emitter blade PCB?

@cshannon2
Copy link
Author

@NoSloppy the short answer is yes. I have seen this side effect discussed in the forums but now I am having a hard time finding the thread. So I will just talk about my experience until I can find the thread. The emitter on my lightsaber has around 9 small leds. When there isn't a blade in the lightsaber and the lightsaber is powered on these leds provide lighting effects. In my experience when BLADE_ID_SCAN_MILLIS is enabled the 9 small leds in the emitter begin to flash / blink. This flash/blink does not occur everytime a blade_id_scan occurs and the blinking/flashing can vary in its brightness. Based off of what I have read in the forums this can be expected due to how BLADE_ID_SCAN_MILLIS functions. By setting a timeout we can prevent the blinking from occuring after the lightsaber is no longer in use. I am not sure if this change has any impact on battery life but I feel like it could potentially be beneficial for battery life.

return true;
bool ScanBladeIdNow() {
uint32_t now = millis();
if (IsOn() == false && (now - blade_id_scan_start_) < BLADE_ID_SCAN_TIMEOUT) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is IsOn() == false here?
That will make blade scanning while on not work properly.

Copy link
Author

@cshannon2 cshannon2 Sep 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The assumption was that a blade config file wouldn't change while the blade was ignited, as a result only search for a blade if the lightsaber is off and the timeout hasn't been reached. If you would like I can just remove the IsOn() check. The resulting if statement would be if ((now - blade_id_scan_start_) < BLADE_ID_SCAN_TIMEOUT)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW I think shutting off BLADE_ID_SCAN_MILLIS when the blade is lit is a good idea. In my limited experiments with it, I've found that scan values can change quite significantly when the blade is lit - particularly if using SnapshotID - resulting the array constantly trying to change when you don't want it to. Indeed I would go further and add a small delay between shutting off the blade and restarting BLADE_ID_SCAN_MILLIS to ensure that unusual scan values don't cause further unwanted array switches.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@profezzorn I just wanted to bump this PR. Do you have any additional thoughts on this change?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW I think shutting off BLADE_ID_SCAN_MILLIS when the blade is lit is a good idea.

Maybe, but we'd need a define for it then.

@profezzorn I just wanted to bump this PR. Do you have any additional thoughts on this change?

It is now conflicting, and cannot be merged.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@profezzorn I have resolved the conflict. I have also added a new define BLADE_ID_SCAN_WHILE_IGNITED with the default value of true. This new define will allow the user to turn off scanning when the blade is ignited. By default it will always scan the blade. The only case it will not scan for a blade is if the blade is on and BLADE_ID_SCAN_WHILE_IGNITED is defined in the user's config to equal false.

Let me know if you have any other concerns.

#define BLADE_ID_SCAN_TIMEOUT 60 * 10 * 1000
#endif
#ifndef BLADE_ID_SCAN_WHILE_IGNITED
#define BLADE_ID_SCAN_WHILE_IGNITED true
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This not usually how feature defines work in ProffieOS.
(They don't usually have any values, and we use #ifdef / #ifndef / defined() to test them.)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@profezzorn I refactored the way the defines where written. I believe they are identical to the other defines. Let me know if this matches the preferred style.

#ifndef BLADE_ID_SCAN_TIMEOUT
#define BLADE_ID_SCAN_TIMEOUT 60 * 10 * 1000

#ifdef BLADE_ID_SCAN_TIMEOUT
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BLADE_ID_SCAN_TIMEOUT was fine (and better) before.
Please change it back.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change has been reverted back.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually this #Ifdef should probably go away now. (See comments further down.)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented the suggestion in the other comment.

#define BLADE_ID_SCAN_WHILE_IGNITED true

#ifdef BLADE_ID_STOP_SCAN_WHILE_IGNITED
bool scan_while_ignited = false;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't want to add variables outside of the function for this.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this was addressed when refactoring the scan variable.

scan = false;
}
else {
scan = true;
}
if (scan == true && (now - blade_id_scan_start_) < BLADE_ID_SCAN_TIMEOUT) {
if (scan == true && (now - blade_id_scan_start_) < scan_timeout) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

scan == true -> scan

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simplified the logic. This line should now read if (scan == true) then perform a scan. The logic to determine set the value of scan was refactored in another line of code.

bool find_blade_again_pending_ = false;
uint32_t last_scan_id_ = 0;
bool ScanBladeIdNow() {
uint32_t now = millis();
bool scan;
if (BLADE_ID_SCAN_WHILE_IGNITED == false && IsOn() == true){
if (scan_while_ignited == false && IsOn() == true){
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would recommend:
bool scan = true;
#ifdef BLADE_ID_STOP_SCAN_WHILE_IGNITED
if (IsOn()) scan=false;
#endif

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code has been implemented.

uint32_t now = millis();

bool scan = true;
#ifdef BLADE_ID_STOP_SCAN_WHILE_IGNITED
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't indent preprocessor statements, makes them harder to see.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

props/prop_base.h Show resolved Hide resolved
}

if (scan == true) {
if (now - last_scan_id_ > BLADE_ID_SCAN_MILLIS) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe move this up to line 596:

bool scan = (now - last_scan_id_) > BLADE_ID_SCAN_MILLIS;

Then line 607 and 608 can just be: if (scan) {

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented

return true;
}
return false;
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

} else {

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

props/prop_base.h Show resolved Hide resolved
#ifndef BLADE_ID_SCAN_TIMEOUT
#define BLADE_ID_SCAN_TIMEOUT 60 * 10 * 1000

#ifdef BLADE_ID_SCAN_TIMEOUT
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually this #Ifdef should probably go away now. (See comments further down.)

#endif

#ifdef BLADE_ID_SCAN_TIMEOUT
#define BLADE_ID_SCAN_TIMEOUT 60 * 10 * 1000
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this line.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GitHub highlighted 4 different lines. Which one are you saying should be removed? Also I am not sure why any of the 4 lines highlighted would be removed.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line:
#define BLADE_ID_SCAN_TIMEOUT 60 * 10 * 1000

It will produce a warning message that BLADE_ID_SCAN_TIMEOUT is already defined.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has been completed. Now with the re-write / refactoring of the feature the user should be able to define a timeout if they want blade id to timeout but it won't effect users who don't specify a timeout.

@@ -356,6 +356,9 @@ class PropBase : CommandParser, Looper, protected SaberBase, public ModeInterfac
BladeSet BladeOff() {
#ifdef IDLE_OFF_TIME
last_on_time_ = millis();
#endif
#ifdef BLADE_ID_SCAN_MILLIS
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this be #ifdef BLADE_ID_SCAN_TIMEOUT ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -1120,6 +1140,13 @@ class PropBase : CommandParser, Looper, protected SaberBase, public ModeInterfac

current_mode->mode_Loop();

#ifdef BLADE_ID_SCAN_MILLIS
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here (#ifdef BLADE_ID_SCAN_TIMEOUT)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -1140,6 +1167,10 @@ class PropBase : CommandParser, Looper, protected SaberBase, public ModeInterfac
#ifdef IDLE_OFF_TIME
uint32_t last_on_time_;
#endif

#ifdef BLADE_ID_SCAN_MILLIS
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and here (#ifdef BLADE_ID_SCAN_TIMEOUT)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants